The concept of an Activity service arose from a requirement to support long running applications for which transactions with atomic, consistent, isolated, and durable (ACID) properties were unsuitable. The main problem with an ACID transaction being that resources accessed under the scope of the transaction remain locked, by the transaction, for the duration of the transaction. This unreasonably limits access to resources if the transaction remains active for an extended period of time. For example, in a widely distributed business process, perhaps involving web-based user interactions and cross-enterprise boundaries, it is neither practical nor scalable to hold resource locks for extended periods of time. As a result an Activity Service framework was defined by the Object Management Group (OMG) and subsequently added to Java 2 Platform, Enterprise Edition (J2EE) by Java Specification Request (JSR) 95-J2EE Activity Service for Extended Transactions, lead by Ian Robinson of IBM.
The purpose of the Activity service is to provide a middleware framework on which extended Unit of Work (UOW) models can be constructed. An extended UOW model might simply provide a means for grouping a related set of tasks that have no transactional properties or it may provide services for a long-running business activity that consists of a number of short-duration ACID transactions. The Activity service is deliberately non-prescriptive in the types of UOW models it supports. The advantage of structuring business processes as activities with looser semantics than ACID transactions, for example by modelling a business process as a series of short-duration ACID transactions within a longer-lived activity, is that the business process may acquire and hold resource locks only for the duration of the ACID transaction rather than the entire duration of the long-running activity.
The Activity service defines a generic middleware framework which provides functions such as UOW scoping and nesting management, context and data propagation with remote method requests, and inter-process signalling between propagated activity scopes. Higher Level Services (HLS), such as extended transactions and other unit of work models, can then be built on this framework, exploiting its functions.
However, whilst such HLSs tend to be fairly complex the Activity service can also be used to build other “lightweight” HLSs (HLSLites) which simply propagate data on remote method calls. The Activity service enables propagation of data without, for example, requiring a change to the remote method definition to add a new parameter, or to write the underlying support code to propagate the data. It is particularly useful if client-specific data needs to be propagated on all method calls from a given client to a remote target. For example, as J2EE evolves, more system services are being defined which have a need to propagate data with J2EE requests. Such HLSLites often provide a quality-of-service and the data they need to propagate may not be specific to the remote method call itself but may be related, for example, to the node from which the request originated (such as locale data) or the individual user that initiated the task (such as a userid). This data may not fit naturally into a scoped context (have no logical “begin” and “end” within the application method) and may not require nesting support, and as such will not require co-ordination or signalling functions. For example, the basic requirement may be the ability to send a single piece of data with every outbound request to a remote target (and perhaps to receive a piece of data on response) and because this requirement is that of a system service the data does not need to be exposed to the application programmer (in fact it is often desirable that it is not exposed). As a result it is undesirable for the data to be transported as a parameter on the request itself. The data may be identical for every request from a particular node (for example, the locale of that node), or there may be potentially different data sent for each request (such as data that is tracking the progress of a distributed request through the system). Further, there may be some requests for which no data needs to be sent.
However, whilst the Activity Service framework provides a base on which to implement such lightweight HLSs it introduces an unnecessary burden, in terms of complexity and performance, which results from being a framework which also provides a base for more complex UOW based services.
Note that in the J2EE environment, for example, as an alternative to using the Activity Service framework, system services are able to propagate data on IIOP requests through implementation of the org.omg.PortableInterceptor interface. Such an implementation is then invoked for every outbound and inbound request and response so that it can send and receive data. For a service that needs to send only a single string of data, though, implementation of its own interceptor introduces a considerable overhead which, if the Activity Service is used, is handled by the Activity Service. For example the system service would need to marshal data into CORBA data types, and more importantly, the format of the data that is sent (the “service context”) has to be defined by the OMG if interoperable services are to be provided by different vendors. Further the service must be present on all nodes through which a request passes in order for the service context to be propagated with the request to all the nodes.
As a result neither the Activity Service nor the PortableInterceptor provide an ideal method for a HLSLite to propagate data and there is therefore a need to provide an alternate framework, or an extension to the Activity service framework, which reduces the burden for lightweight HLSs which do not require all of the facilities of the Activity Service and for which a PortableInterceptor provides an inadequate and/or too complex solution.